home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / lice / mkdepend / main.c < prev    next >
C/C++ Source or Header  |  1991-09-04  |  14KB  |  689 lines

  1. /*
  2. //
  3. // Copyright (C) 1991 Texas Instruments Incorporated.
  4. //
  5. // Permission is granted to any individual or institution to use, copy, modify,
  6. // and distribute this software, provided that this complete copyright and
  7. // permission notice is maintained, intact, in all copies and supporting
  8. // documentation.
  9. //
  10. // Texas Instruments Incorporated provides this software "as is" without
  11. // express or implied warranty.
  12. //
  13.  * $XConsortium: main.c,v 1.33 89/07/21 11:35:21 jim Exp $
  14.  */
  15. #include "def.h"
  16. #ifdef hpux
  17. #define sigvec sigvector
  18. #endif /* hpux */
  19.  
  20. #include <signal.h>
  21. #include <errno.h>
  22. #ifdef VMS
  23. #include <unixio.h>
  24. #endif
  25.  
  26. #ifdef DEBUG
  27. int    debug;
  28. #endif
  29.  
  30. /**
  31.  ** MODIFIED: 06/25/90 by MBN
  32.  **
  33.  ** Added the -X option to generate dependencies for a file but *not* an RCS
  34.  ** dependency. This is useful for LEX and YACC generated files that have 
  35.  ** include statements, but whose source is machine-produced.
  36.  **/
  37.  
  38. /**
  39.  ** MODIFIED: 06/13/90 by MBN
  40.  **
  41.  ** Modified basename() function to check extensions and added SourceExtensions 
  42.  ** array of valid source filename extensions.
  43.  **/
  44.  
  45. /**
  46.  ** MODIFIED: 06/08/90 by MBN
  47.  **
  48.  ** Add a dependency to automatically link each header file when checkout
  49.  ** out to the project include directory if the command line option -L 
  50.  ** is specified
  51.  **/
  52.  
  53. /**
  54.  ** MODIFIED: 05/16/90 by MBN
  55.  **
  56.  ** Add a dependency for each file in the file list on the command line to
  57.  ** its RCS master of the form "foo.h :: $(RCSDIR)foo.h$(RCSEXT)" if the
  58.  ** command line option -R (for RCS) is specified
  59.  **/
  60.  
  61. /**
  62.  ** MODIFIED: 05/14/90 by MBN
  63.  **
  64.  ** If the extension on a file is .l, .y, .h, .c, or .C don't zap it! This 
  65.  ** allows mkdepend to calculate dependencies for files contained in the SRCS
  66.  ** list in the Imake file. If this is not done, then "foo.h" becomes "foo.o"
  67.  **/
  68.  
  69. /**
  70.  ** MODIFIED: 05/11/90 by MBN
  71.  **
  72.  ** Removed hard-coded path separator character and changed to a user-defined
  73.  ** character constant. The symbol PATHSEP defaults to '/' but can be over
  74.  ** ridden on the command line to mkdepend.
  75.  **/
  76.  
  77. char path_sep = PATHSEP;
  78. /* The following is used to find the end of the directory information.  In
  79.    UNIX, it is '/'; in VMS, however, it is ']', which differs from the path
  80.    separator '.'.
  81.    */
  82. char path_end = PATHSEP;
  83.  
  84. char *ProgramName;
  85.  
  86. char    *directives[] = {
  87.     "if",
  88.     "ifdef",
  89.     "ifndef",
  90.     "else",
  91.     "endif",
  92.     "define",
  93.     "undef",
  94.     "include",
  95.     "line",
  96.     "pragma",
  97.     "error",
  98.     "ident",
  99.     "sccs",
  100.     "elif",
  101.     "eject",
  102.     NULL
  103. };
  104.  
  105. /**
  106.  ** SourceExtensions contains the extensions for files that have conversion
  107.  ** rules, that is, get transposed from one type of "thing" to another. Any
  108.  ** file passed on the command line that does *NOT* have one of these extensions
  109.  ** is assumed to be a miscellaneous file and, if the -R (RCS Checkout) flag
  110.  ** is provided, will result in a dependency added for to check out the file
  111.  ** from under RCS control.
  112.  **/
  113.  
  114. char *SourceExtensions[] = {
  115.     "h",
  116.     "hxx",
  117.     "c",
  118.     "cxx",
  119.     "C",
  120.     "y",
  121.     "Y",
  122.     "l",
  123.     "L",
  124.     NULL
  125. };
  126.  
  127. struct symtab    predefs[] = {
  128. #ifdef apollo
  129.     {"apollo", NULL},
  130. #endif
  131. #ifdef ibm032
  132.     {"ibm032", NULL},
  133. #endif
  134. #ifdef sun
  135.     {"sun", NULL},
  136. #endif
  137. #ifdef os2
  138.     {"os2", NULL},
  139. #endif
  140. #ifdef DOS
  141.     {"DOS", NULL},
  142. #endif
  143. #ifdef hpux
  144.     {"hpux", NULL},
  145. #endif
  146. #ifdef vax
  147.     {"vax", NULL},
  148. #endif
  149. #ifdef VMS
  150.     {"VMS", NULL},
  151. #endif
  152. #ifdef cray
  153.     {"cray", NULL},
  154. #endif
  155. #ifdef CRAY
  156.     {"CRAY", NULL},
  157. #endif
  158. #ifdef att
  159.     {"att", NULL},
  160. #endif
  161. #ifdef mips
  162.     {"mips", NULL},
  163. #endif
  164. #ifdef ultrix
  165.     {"ultrix", NULL},
  166. #endif
  167. #ifdef mc68000
  168.     {"mc68000", NULL},
  169. #endif
  170. #ifdef mc68020
  171.     {"mc68020", NULL},
  172. #endif
  173. #ifdef __GNUC__
  174.     {"__GNUC__", NULL},
  175. #endif
  176. #ifdef __STDC__
  177.     {"__STDC__", NULL},
  178. #endif
  179.     {NULL, NULL}
  180. };
  181.  
  182. struct symtab    deflist[ MAXDEFINES ];
  183. struct    inclist inclist[ MAXFILES ],
  184.         *inclistp = inclist;
  185.  
  186. char    *filelist[ MAXFILES ];
  187. char    *dependonlylist[ MAXFILES ];
  188. char    *includedirs[ MAXDIRS ];
  189. char    *notdotdot[ MAXDIRS ];
  190. char    *objfile = ".o";
  191. char    *startat = "# DO NOT DELETE THIS LINE -- mkdepend depends on it.";
  192. int    width = 78;
  193. boolean    printed = FALSE;
  194. boolean    verbose = FALSE;
  195. boolean    show_where_not = FALSE;
  196. boolean rcs_dependency = FALSE;
  197. boolean link_dependency = FALSE;
  198.  
  199. void redirect();
  200.  
  201. static
  202. #ifdef SIGNALRETURNSINT
  203. int
  204. #else
  205. void
  206. #endif
  207. catch (sig)
  208.     int sig;
  209. {
  210.     fflush (stdout);
  211.     log_fatal ("got signal %d\n", sig);
  212. }
  213.  
  214. #ifndef os2
  215. #ifndef USG
  216. struct sigvec sig_vec = {
  217.     catch,
  218.      (1<<(SIGINT -1))
  219.     |(1<<(SIGQUIT-1))
  220.     |(1<<(SIGBUS-1))
  221.     |(1<<(SIGILL-1))
  222.     |(1<<(SIGSEGV-1))
  223.     |(1<<(SIGHUP-1))
  224.     |(1<<(SIGPIPE-1))
  225.     |(1<<(SIGSYS-1)),
  226.     0
  227. };
  228. #endif /* USG */
  229. #endif /* os2 */
  230.  
  231. main(argc, argv)
  232.     int    argc;
  233.     char    **argv;
  234. {
  235.     register struct symtab    *symp = deflist;
  236.     register char    **fp = filelist;
  237.     register char    **incp = includedirs;
  238.     register char    **temp;
  239.     register char    **dp = dependonlylist;
  240.     register char    *p;
  241.     register struct inclist    *ip;
  242.     char    *makefile = NULL;
  243.     struct filepointer    *filecontent;
  244.     struct symtab *psymp = predefs;
  245.     char *endmarker = NULL;
  246.     char buf[ 2 ];
  247.  
  248.     ProgramName = argv[0];
  249.  
  250.     while (psymp->s_name)
  251.         *symp++ = *psymp++;
  252.     for(argc--, argv++; argc; argc--, argv++) {
  253.             /* if looking for endmarker then check before parsing */
  254.         if (endmarker && strcmp (endmarker, *argv) == 0) {
  255.             endmarker = NULL;
  256.             continue;
  257.         }
  258.         if (**argv != '-') {
  259.             /* scan existing filenames and only add to list if
  260.                this new one has not already been specified */
  261.             for (temp = filelist; *temp; temp++)
  262.                 if(strcmp(argv[0],*temp) == 0)
  263.                 break;
  264.             if (*temp == NULL)
  265.                 *fp++ = argv[0];
  266.             continue;
  267.         }
  268.         switch(argv[0][1]) {
  269.         case '-':
  270.             endmarker = &argv[0][2];
  271.             if (endmarker[0] == '\0') endmarker = "--";
  272.             break;
  273.         case 'D':
  274.             symp->s_name = argv[0]+2;
  275.             if (*symp->s_name == '\0') {
  276.                 symp->s_name = *(++argv);
  277.                 argc--;
  278.             }
  279.             for (p=symp->s_name; *p ; p++)
  280.                 if (*p == '=') {
  281.                     *p++ = '\0';
  282.                     break;
  283.                 }
  284.             symp->s_value = p;
  285.             symp++;
  286.             break;
  287.         case 'R':
  288.             rcs_dependency = TRUE;
  289.             break;
  290.         case 'L':
  291.             link_dependency = TRUE;
  292.             break;
  293.               case 'X':
  294.             if(argv[0][2] != ' ' && argv[0][2] != '\0')
  295.             {
  296.                 *dp++ = &(argv[0][2]);
  297.                 *fp++ = &(argv[0][2]);
  298.             }
  299.             break;
  300.         case 'I':
  301.             *incp++ = argv[0]+2;
  302.             if (**(incp-1) == '\0') {
  303.                 *(incp-1) = *(++argv);
  304.                 argc--;
  305.             }
  306.             break;
  307.         /* do not use if endmarker processing */
  308.         case 'w':
  309.             if (endmarker) break;
  310.             if (argv[0][2] == '\0') {
  311.                 argv++;
  312.                 argc--;
  313.                 width = atoi(argv[0]);
  314.             } else
  315.                 width = atoi(argv[0]+2);
  316.             break;
  317.         case 'o':
  318.             if (endmarker) break;
  319.             if (argv[0][2] == '\0') {
  320.                 argv++;
  321.                 argc--;
  322.                 objfile = argv[0];
  323.             } else
  324.                 objfile = argv[0]+2;
  325.             break;
  326.         case 'v':
  327.             if (endmarker) break;
  328.             verbose = TRUE;
  329. #ifdef DEBUG
  330.             if (argv[0][2])
  331.                 debug = atoi(argv[0]+2);
  332. #endif
  333.             break;
  334.         case 's':
  335.             if (endmarker) break;
  336.             startat = argv[0]+2;
  337.             if (*startat == '\0') {
  338.                 startat = *(++argv);
  339.                 argc--;
  340.             }
  341.             if (*startat != '#')
  342.                 log_fatal("-s flag's value should start %s\n",
  343.                     "with '#'.");
  344.             break;
  345.         case 'f':
  346.             if (endmarker) break;
  347.             makefile = argv[0]+2;
  348.             if (*makefile == '\0') {
  349.                 makefile = *(++argv);
  350.                 argc--;
  351.             }
  352.             break;
  353.  
  354.         case 'P':    /* User-specified path separator character */
  355.             if( argv[0][2] == '\0' || argv[0][2] == ' ')
  356.                 log_fatal("invalid pathname separator specified\n");
  357.             path_sep = argv[0][2];
  358.             break;
  359.                     
  360.         case 'Q':    /* User-specified path end character */
  361.             path_end = argv[0][2];
  362.             break;
  363.                     
  364.         /* Ignore -O, -g so we can just pass ${CFLAGS} to
  365.            makedepend
  366.          */
  367.         case 'O':
  368.         case 'g':
  369.             break;
  370.         default:
  371.             if (endmarker) break;
  372.     /*        log_fatal("unknown opt = %s\n", argv[0]); */
  373.             do_log("ignoring option %s\n", argv[0]);
  374.         }
  375.     }
  376.  
  377.     redirect(startat, makefile);
  378.  
  379.     /*
  380.      * catch signals.
  381.      */
  382. #ifdef USG
  383. /*  should really reset SIGINT to SIG_IGN if it was.  */
  384.     signal (SIGHUP, catch);
  385.     signal (SIGINT, catch);
  386.     signal (SIGQUIT, catch);
  387.     signal (SIGILL, catch);
  388.     signal (SIGBUS, catch);
  389.     signal (SIGSEGV, catch);
  390.     signal (SIGSYS, catch);
  391. #else
  392. #ifndef os2
  393.     sigvec(SIGHUP, &sig_vec, (struct sigvec *)0);
  394.     sigvec(SIGINT, &sig_vec, (struct sigvec *)0);
  395.     sigvec(SIGQUIT, &sig_vec, (struct sigvec *)0);
  396.     sigvec(SIGILL, &sig_vec, (struct sigvec *)0);
  397.     sigvec(SIGBUS, &sig_vec, (struct sigvec *)0);
  398.     sigvec(SIGSEGV, &sig_vec, (struct sigvec *)0);
  399.     sigvec(SIGSYS, &sig_vec, (struct sigvec *)0);
  400. #endif
  401. #endif
  402.  
  403.     /*
  404.      * now peruse through the list of files.
  405.      */
  406.     for(fp=filelist; *fp; fp++) {
  407.         if(is_source_file(*fp)) {
  408.         filecontent = getfile(*fp);
  409.         ip = newinclude(*fp, (char *)NULL);
  410.         find_includes(filecontent, ip, ip, 0);
  411.         freefile(filecontent);
  412.         recursive_pr_include(ip, ip->i_file, *fp);
  413.         }
  414.  
  415.         if(is_depend_only_file(*fp) == TRUE) {
  416.         sprintf(buf, "\n");
  417.         fwrite(buf, strlen(buf), 1, stdout);
  418.         }
  419.         else if(rcs_dependency == TRUE) {
  420.         rcs_pr(*fp, "$(RCSDIR)", "$(RCSEXT)");
  421.         if (link_dependency == TRUE)
  422.             link_pr(*fp);
  423.         }
  424.         inc_clean();
  425.     }
  426.     if (printed)
  427.         printf("\n");
  428.     exit(0);
  429. }
  430.  
  431. int is_source_file(file)
  432.     register char    *file;
  433. {
  434.     register char    *p, **q;
  435.  
  436.     for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
  437.  
  438.     if (*p == path_sep)
  439.         p++;
  440.  
  441.     file = copy(p);
  442.     for(p=file+strlen(file); p>file && *p != '.'; p--) ;
  443.  
  444.     if (*p == '.')
  445.     {
  446.         for( q = SourceExtensions; *q; q++)
  447.         if( !strcmp(*q, (p+1)) )
  448.         {
  449.         return 1;
  450.         }
  451.     }
  452.     return 0;
  453. }
  454.  
  455. int is_depend_only_file(file)
  456.     register char    *file;
  457. {
  458.     register char    *p, **q;
  459.  
  460.     for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
  461.  
  462.     if (*p == path_sep)
  463.         p++;
  464.  
  465.     for( q = dependonlylist; *q; q++)
  466.     if( !strcmp(*q, p) )
  467.         return 1;
  468.     return 0;
  469. }
  470.  
  471. struct filepointer *getfile(file)
  472.     char    *file;
  473. {
  474.     register int    i;
  475.     struct filepointer    *content;
  476.     struct stat    st;
  477.     FILE   *fd;
  478.  
  479.     content = (struct filepointer *)malloc(sizeof(struct filepointer));
  480.     if ((fd = fopen(file, "r")) == NULL) {
  481.         do_log("cannot open \"%s\" [errno=%d]\n", file, errno);
  482.         content->f_p = content->f_base = content->f_end = malloc(1);
  483.         *content->f_p = '\0';
  484.         return(content);
  485.     }
  486.     stat(file, &st);
  487.     content->f_len = st.st_size+1;
  488.     content->f_base = malloc(content->f_len);
  489.     if (content->f_base == NULL)
  490.       log_fatal("cannot allocate mem\n");
  491.     for (i = 0; i < st.st_size; ++i)
  492.       content->f_base[i] = getc (fd);
  493.     fclose(fd);
  494.     content->f_p = content->f_base;
  495.     content->f_end = content->f_base + st.st_size;
  496.     *content->f_end = '\0';
  497.     content->f_line = 0;
  498.     return(content);
  499. }
  500.  
  501. freefile(fp)
  502.     struct filepointer    *fp;
  503. {
  504.     free(fp->f_base);
  505.     free(fp);
  506. }
  507.  
  508. /*VARARGS*/
  509. log_fatal(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
  510. char* x0;
  511. {
  512.     do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
  513.     exit (1);
  514. }
  515.  
  516. /*VARARGS0*/
  517. do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
  518. char* x0;
  519. {
  520.     fprintf(stderr, "%s:  ", ProgramName);
  521.     fprintf(stderr, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
  522. }
  523.  
  524. char *copy(str)
  525.     register char    *str;
  526. {
  527.     register char    *p = malloc(strlen(str) + 1);
  528.  
  529.     strcpy(p, str);
  530.     return(p);
  531. }
  532.  
  533. match(str, list)
  534.     register char    *str, **list;
  535. {
  536.     register int    i;
  537.  
  538.     for (i=0; *list; i++, list++)
  539.         if (strcmp(str, *list) == 0)
  540.             return(i);
  541.     return(-1);
  542. }
  543.  
  544. /*
  545.  * Get the next line.  We only return lines beginning with '#' since that
  546.  * is all this program is ever interested in.
  547.  */
  548. char *getline(filep)
  549.     register struct filepointer    *filep;
  550. {
  551.     register char    *p,    /* walking pointer */
  552.             *eof,    /* end of file pointer */
  553.             *bol;    /* beginning of line pointer */
  554.     register    lineno;    /* line number */
  555.  
  556.     p = filep->f_p;
  557.     eof = filep->f_end;
  558.     if (p >= eof)
  559.         return((char *)NULL);
  560.     lineno = filep->f_line;
  561.  
  562.     for(bol = p--; ++p < eof; ) {
  563.         if (*p == '/' && *(p+1) == '*') { /* consume comments */
  564.             *p++ = ' ', *p++ = ' ';
  565.             while (*p) {
  566.                 if (*p == '*' && *(p+1) == '/') {
  567.                     *p++ = ' ', *p = ' ';
  568.                     break;
  569.                 }
  570.                 else if (*p == '\n')
  571.                     lineno++;
  572.                 *p++ = ' ';
  573.             }
  574.             continue;
  575.         }
  576.         if (*p == '/' && *(p+1) == '/') { /* consume EOL comments */
  577.             *p++ = ' ', *p++ = ' ';
  578.             while (*p != '\n') { *p++ = ' '; }
  579.         }
  580.         if (*p == '\n') {
  581.             lineno++;
  582.             if (*bol == '#') {
  583.                 register char *cp;
  584.  
  585.                 *p++ = '\0';
  586.                 /* punt lines with just # (yacc generated) */
  587.                 for (cp = bol+1; 
  588.                      *cp && (*cp == ' ' || *cp == '\t'); cp++);
  589.                 if (*cp) goto done;
  590.             }
  591.             bol = p+1;
  592.         }
  593.     }
  594.     if (*bol != '#')
  595.         bol = NULL;
  596. done:
  597.     filep->f_p = p;
  598.     filep->f_line = lineno;
  599.     return(bol);
  600. }
  601.  
  602. #ifdef VMS
  603. void unlink (name)
  604.      char *name;
  605. {
  606.   char command[200];
  607.   /* Use the DELETE command (executed through SYSTEM), since VMS does not
  608.      support UNLINK */
  609.   sprintf (command, "delete %s;", name);
  610.   system (command);
  611. }
  612. #endif
  613.  
  614. #ifdef USG
  615. int rename (from, to)
  616.     char *from, *to;
  617. {
  618.     (void) unlink (to);
  619.     if (link (from, to) == 0) {
  620.     unlink (from);
  621.     return 0;
  622.     } else {
  623.     return -1;
  624.     }
  625. }
  626. #endif /* USG */
  627.  
  628. void
  629. redirect(line, makefile)
  630.     char    *line,
  631.         *makefile;
  632. {
  633.     struct stat    st;
  634.     FILE    *fdin, *fdout;
  635.     char    backup[ BUFSIZ ],
  636.         buf[ BUFSIZ ];
  637.     boolean    found = FALSE;
  638.     int    len;
  639.  
  640.     /*
  641.      * if makefile is "-" then let it pour onto stdout.
  642.      */
  643.     if (makefile && *makefile == '-' && *(makefile+1) == '\0')
  644.         return;
  645.  
  646.     /*
  647.      * use a default makefile is not specified.
  648.      */
  649.     if (!makefile) {
  650.         if (stat("makefile", &st) == 0)
  651.             makefile = "makefile";
  652.         else if (stat("Makefile", &st) == 0)
  653.             makefile = "Makefile";
  654.         else
  655.             log_fatal("[mM]akefile is not present\n");
  656.     }
  657.     else
  658.         stat(makefile, &st);
  659.     if ((fdin = fopen(makefile, "r")) == NULL)
  660.         log_fatal("cannot open \"%s\"\n", makefile);
  661.     sprintf(backup, "%s.bak", makefile);
  662.     unlink(backup);
  663.     fclose(fdin);
  664.     if (rename(makefile, backup) < 0)
  665.         log_fatal("cannot rename %s to %s\n", makefile, backup);
  666.     fdin = fopen(backup, "r");
  667.     if ((fdout = freopen(makefile, "w", stdout)) == NULL)
  668.         log_fatal("cannot open \"%s\"\n", backup);
  669.     len = strlen(line);
  670.     while (fgets(buf, BUFSIZ, fdin) && !found) {
  671.         if (*buf == '#' && strncmp(line, buf, len) == 0)
  672.             found = TRUE;
  673.         fputs(buf, fdout);
  674.     }
  675.     if (!found) {
  676.         if (verbose)
  677.         do_log("Adding new delimiting line \"%s\" and dependencies...\n",
  678.             line);
  679.         puts(line); /* same as fputs(fdout); but with newline */
  680.     }
  681.     fflush(fdout);
  682. #ifdef USG
  683.     chmod(makefile, st.st_mode);
  684. #else
  685. /*        fchmod(fileno(fdout), st.st_mode); */
  686.         chmod(makefile, st.st_mode);
  687. #endif /* USG */
  688. }
  689.